'''
用户
'''
from pydantic import BaseModel, EmailStr, validator
from typing import Optional, Dict, Any,Tuple, List
import os
from dotenv import load_dotenv
from db.redis_server import redis_client
from db.mysql_server import CvvManatukuUser,CvvUser,CvvCardData,DoesNotExist
import datetime
import jwt
from fastapi import HTTPException, Depends, status,APIRouter
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import hashlib
import secrets
import string

# 加载环境变量
load_dotenv()
# 请求/响应模型
class LoginRequest(BaseModel):
    identifier: str  # 用户名或邮箱
    password: str


class LoginResponse(BaseModel):
    success: bool
    message: str
    token: Optional[str] = None
    user_info: Optional[Dict[str, Any]] = None


# 用户信息模型
class UserInfo(BaseModel):
    user_id: int
    username: str
    email: str
    user_type: int

    class Config:
        orm_mode = True  # 允许从ORM对象转换


# Token数据模型
class TokenData(BaseModel):
    user_id: int
    username: str
    user_type: int
    token: str


class AddUserRequest(BaseModel):
    username: str
    email: EmailStr
    password: str
    user_type: int = 1  # 默认普通用户
    status: int = 1  # 默认正常状态
    query_count: int = 9999  # 默认查询次数

# 添加用户响应模型
class AddUserResponse(BaseModel):
    success: bool
    message: str
    user_id: Optional[int] = None
    username: Optional[str] = None


class JWTConfig:
    def __init__(self):
        self.secret_key = os.getenv('JWT_SECRET_KEY', 'your-secret-key-change-this')
        self.algorithm = os.getenv('JWT_ALGORITHM', 'HS256')
        self.token_expiry_hours = int(os.getenv('JWT_EXPIRY_HOURS', 24))


async def verify_token(credentials: HTTPAuthorizationCredentials = Depends(HTTPBearer())) -> TokenData:
    """验证JWT token"""
    print(f"🔑 验证Token: {credentials.credentials}")
    # 硬编码返回管理员 - 仅用于测试
    return TokenData(
        user_id=1,
        username="admin",
        user_type=2,
        token=credentials.credentials
    )

async def get_current_user(token_data: TokenData = Depends(verify_token)) -> UserInfo:
    """获取当前用户信息"""
    print(f"👤 获取当前用户: {token_data}")
    return UserInfo(
        user_id=token_data.user_id,
        username=token_data.username,
        email="admin@example.com",
        user_type=token_data.user_type
    )

class AuthService:
    def __init__(self):
        self.jwt_config = JWTConfig()
        self.security = HTTPBearer()

    def hash_password(self, password: str, salt: str) -> str:
        """密码加密方法"""
        return hashlib.sha256((password + salt).encode()).hexdigest()

    def verify_user_status(self, user: CvvUser) -> Tuple[bool, str]:
        """验证用户状态"""
        if not user:
            return False, "用户不存在"

        if user.delete_flag == 1:
            return False, "用户已被删除"

        if user.status == 0:
            return False, "账号已被封禁"

        if user.status != 1:
            return False, "账号状态异常"

        if user.expiry_time and user.expiry_time < datetime.datetime.now():
            return False, "账号已过期"

        if user.query_count <= 0:
            return False, "查询次数已用完"

        return True, "验证通过"

    def generate_token(self, user_id: int, username: str, user_type: int) -> str:
        """生成JWT token"""
        payload = {
            'user_id': user_id,
            'username': username,
            'user_type': user_type,
            'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=self.jwt_config.token_expiry_hours),
            'iat': datetime.datetime.utcnow()
        }
        return jwt.encode(payload, self.jwt_config.secret_key, algorithm=self.jwt_config.algorithm)

    # async def verify_token(self, credentials: HTTPAuthorizationCredentials = Depends(HTTPBearer())) -> TokenData:
    #     """验证JWT token并返回包含token字符串的数据"""
    #     token = credentials.credentials
    #     return TokenData(user_id=123, username="admin", user_type=2)
    #     try:
    #         token = credentials.credentials
    #
    #         # 检查Redis中是否存在该token
    #         redis_data = redis_client.get_token_data(token)
    #         if not redis_data:
    #             raise HTTPException(
    #                 status_code=status.HTTP_401_UNAUTHORIZED,
    #                 detail="Token已过期或无效"
    #             )
    #
    #         # 验证JWT签名
    #         payload = jwt.decode(
    #             token,
    #             self.jwt_config.secret_key,
    #             algorithms=[self.jwt_config.algorithm]
    #         )
    #
    #         user_id = payload.get('user_id')
    #         username = payload.get('username')
    #         user_type = payload.get('user_type')
    #
    #         if user_id is None or username is None:
    #             raise HTTPException(
    #                 status_code=status.HTTP_401_UNAUTHORIZED,
    #                 detail="无效的token"
    #             )
    #
    #         # 验证Redis中的数据与JWT payload一致
    #         if (redis_data.get('user_id') != user_id or
    #                 redis_data.get('username') != username):
    #             raise HTTPException(
    #                 status_code=status.HTTP_401_UNAUTHORIZED,
    #                 detail="Token数据不一致"
    #             )
    #
    #         return TokenData(
    #             user_id=user_id,
    #             username=username,
    #             user_type=user_type,
    #             token=token
    #         )
    #
    #     except jwt.ExpiredSignatureError:
    #         # 从Redis中删除过期的token
    #         if hasattr(credentials, 'credentials'):
    #             redis_client.delete_token(credentials.credentials)
    #         raise HTTPException(
    #             status_code=status.HTTP_401_UNAUTHORIZED,
    #             detail="Token已过期"
    #         )
    #     except jwt.InvalidTokenError:
    #         raise HTTPException(
    #             status_code=status.HTTP_401_UNAUTHORIZED,
    #             detail="无效的token"
    #         )

    async def login(self, login_request: LoginRequest) -> LoginResponse:
        """
        用户登录方法
        """
        try:
            # 查询用户信息
            try:
                user = CvvUser.get(
                    (CvvUser.username == login_request.identifier) |
                    (CvvUser.email == login_request.identifier)
                )
            except Exception as e:
                return LoginResponse(
                    success=False,
                    message="用户名或密码错误",
                    token=None
                )

            # 检查用户是否被删除
            if user.delete_flag == 1:
                return LoginResponse(
                    success=False,
                    message="用户已被删除",
                    token=None
                )

            # 验证用户状态
            status_ok, status_msg = self.verify_user_status(user)
            if not status_ok:
                return LoginResponse(
                    success=False,
                    message=status_msg,
                    token=None
                )

            # 验证密码
            hashed_password = self.hash_password(login_request.password, user.salt)
            if hashed_password != user.password:
                # 密码错误，更新错误次数
                new_error_count = user.error_count + 1
                status_val = 0 if new_error_count >= 5 else user.status

                # 更新错误次数和状态
                user.error_count = new_error_count
                user.status = status_val
                user.update_time = datetime.datetime.now()
                user.save()

                return LoginResponse(
                    success=False,
                    message="用户名或密码错误",
                    token=None
                )

            # 密码正确，重置错误次数为0，更新登录时间
            if user.error_count > 0:
                user.error_count = 0
                user.update_time = datetime.datetime.now()
                user.save()

            # 生成token
            token = self.generate_token(user.id, user.username, user.user_type)

            # 存储token到Redis
            user_data = {
                'user_id': user.id,
                'username': user.username,
                'email': user.email,
                'user_type': user.user_type,
                'login_time': datetime.datetime.now().isoformat()
            }

            if redis_client.set_token(token, user_data):
                # 将token添加到用户token列表
                redis_client.add_user_token(user.id, token)
            else:
                print("警告: Token存储到Redis失败，但登录成功")

            # 返回用户信息
            user_info = {
                'user_id': user.id,
                'username': user.username,
                'email': user.email,
                'user_type': user.user_type
            }

            return LoginResponse(
                success=True,
                message="登录成功",
                token=token,
                user_info=user_info
            )

        except Exception as e:
            return LoginResponse(
                success=False,
                message=f"登录失败: {str(e)}",
                token=None
            )

    async def logout(self, token_data: TokenData = Depends(verify_token)) -> Dict[str, Any]:
        """用户登出"""
        try:
            token = token_data.token
            user_id = token_data.user_id

            # 从用户token列表中移除
            redis_client.remove_user_token(user_id, token)
            # 删除token本身
            success = redis_client.delete_token(token)

            return {
                "success": success,
                "message": "登出成功" if success else "登出失败"
            }
        except Exception as e:
            print(f"登出失败: {e}")
            return {
                "success": False,
                "message": f"登出失败: {str(e)}"
            }

    # async def get_current_user(self, token_data: TokenData = Depends(lambda: self.verify_token)) -> UserInfo:
    #     """获取当前用户信息"""
    #     #todo 测试
    #     return UserInfo(
    #         user_id=token_data.user_id,
    #         username=token_data.username,
    #         email="123@qq.com",
    #         user_type=token_data.user_type
    #     )
    #     try:
    #         # 从数据库获取用户信息
    #         user = CvvUser.get_by_id(token_data.user_id)
    #
    #         # 检查用户是否被删除
    #         if user.delete_flag == 1:
    #             raise HTTPException(
    #                 status_code=status.HTTP_401_UNAUTHORIZED,
    #                 detail="用户不存在或已被删除"
    #             )
    #
    #         # 验证用户状态
    #         status_ok, status_msg = self.verify_user_status(user)
    #         if not status_ok:
    #             raise HTTPException(
    #                 status_code=status.HTTP_401_UNAUTHORIZED,
    #                 detail=status_msg
    #             )
    #
    #         return UserInfo(
    #             user_id=user.id,
    #             username=user.username,
    #             email=user.email,
    #             user_type=user.user_type
    #         )
    #
    #     except CvvUser.DoesNotExist:  # 修复：使用正确的异常类
    #         raise HTTPException(
    #             status_code=status.HTTP_401_UNAUTHORIZED,
    #             detail="用户不存在或已被删除"
    #         )

    async def force_logout(self, user_id: int) -> bool:
        """强制用户登出（清除所有token）"""
        try:
            tokens = redis_client.get_user_tokens(user_id)
            for token in tokens:
                redis_client.delete_token(token)
            # 清空用户token列表
            redis_client.set_user_tokens(user_id, [])
            return True
        except Exception as e:
            print(f"强制登出失败: {e}")
            return False

    def generate_salt(self, length: int = 16) -> str:
        """生成随机salt"""
        characters = string.ascii_letters + string.digits
        return ''.join(secrets.choice(characters) for _ in range(length))

    async def add_user(self, user_data: AddUserRequest, current_user: UserInfo) -> AddUserResponse:
        """
        添加新用户（需要管理员权限）
        """
        try:
            # 检查当前用户是否有管理员权限
            if current_user.user_type != 2:  # 2是管理员
                return AddUserResponse(
                    success=False,
                    message="权限不足，需要管理员权限"
                )

            # 检查用户名是否已存在
            try:
                existing_user = CvvUser.get(
                    (CvvUser.username == user_data.username) &
                    (CvvUser.delete_flag == 0)
                )
                return AddUserResponse(
                    success=False,
                    message="用户名已存在"
                )
            except Exception as e:
                    pass


            # 检查邮箱是否已存在
            try:
                existing_user = CvvUser.get(
                    (CvvUser.email == user_data.email) &
                    (CvvUser.delete_flag == 0)
                 )
                return AddUserResponse(
                    success=False,
                    message="邮箱已存在"
                )
            except Exception as e:
                pass


            # 生成salt和加密密码
            salt = self.generate_salt()
            hashed_password = self.hash_password(user_data.password, salt)

             # 创建新用户
            new_user = CvvUser.create(
                username=user_data.username,
                email=user_data.email,
                salt=salt,
                password=hashed_password,
                user_type=user_data.user_type,
                status=user_data.status,
                query_count=user_data.query_count
            )

            return AddUserResponse(
                success=True,
                message="用户添加成功",
                user_id=new_user.id,
                username=new_user.username
            )

        except Exception as e:
            return AddUserResponse(
                success=False,
                message=f"添加用户失败: {str(e)}"
            )

    async def update_user(self, user_id: int, user_data: Dict[str, Any], current_user: UserInfo) -> Dict[str, Any]:
        """
        更新用户信息（需要管理员权限）
        """
        try:
            # 检查当前用户是否有管理员权限
            if current_user.user_type != 2:
                return {
                    "success": False,
                    "message": "权限不足，需要管理员权限"
                }

            # 获取要更新的用户
            try:
                user = CvvUser.get_by_id(user_id)
            except CvvUser.DoesNotExist:
                return {
                    "success": False,
                    "message": "用户不存在"
                }

            # 检查用户是否被删除
            if user.delete_flag == 1:
                return {
                    "success": False,
                    "message": "用户已被删除"
                }

            # 更新字段
            update_fields = {}
            allowed_fields = ['user_type', 'status', 'query_count', 'expiry_time']

            for field in allowed_fields:
                if field in user_data:
                    update_fields[field] = user_data[field]

            # 如果更新了密码
            if 'password' in user_data and user_data['password']:
                salt = self.generate_salt()
                hashed_password = self.hash_password(user_data['password'], salt)
                update_fields['salt'] = salt
                update_fields['password'] = hashed_password

            # 执行更新
            if update_fields:
                update_fields['update_time'] = datetime.datetime.now()
                query = CvvUser.update(**update_fields).where(CvvUser.id == user_id)
                query.execute()

            return {
                "success": True,
                "message": "用户信息更新成功",
                "user_id": user_id
            }

        except Exception as e:
            return {
                "success": False,
                "message": f"更新用户信息失败: {str(e)}"
            }

    async def delete_user(self, user_id: int, current_user: UserInfo) -> Dict[str, Any]:
        """
        删除用户（软删除，需要管理员权限）
        """
        try:
            # 检查当前用户是否有管理员权限
            if current_user.user_type != 2:
                return {
                    "success": False,
                    "message": "权限不足，需要管理员权限"
                }

            # 不能删除自己
            if user_id == current_user.user_id:
                return {
                    "success": False,
                    "message": "不能删除自己的账户"
                }

            # 获取要删除的用户
            try:
                user = CvvUser.get_by_id(user_id)
            except CvvUser.DoesNotExist:
                return {
                    "success": False,
                    "message": "用户不存在"
                }

            # 检查用户是否已被删除
            if user.delete_flag == 1:
                return {
                    "success": False,
                    "message": "用户已被删除"
                }

            # 软删除用户
            user.delete_flag = 1
            user.update_time = datetime.datetime.now()
            user.save()

            # 强制该用户登出
            await self.force_logout(user_id)

            return {
                "success": True,
                "message": "用户删除成功",
                "user_id": user_id
            }

        except Exception as e:
            return {
                "success": False,
                "message": f"删除用户失败: {str(e)}"
            }


auth_service = AuthService()

router = APIRouter()



# 路由
@router.post("/auth/login", summary="用户登录")
async def login(login_request: LoginRequest):
    """用户登录接口"""
    return await auth_service.login(login_request)


@router.post("/auth/logout", summary="用户登出")
async def logout(token_data: TokenData = Depends(verify_token)):
    """用户登出接口"""
    return await auth_service.logout(token_data)


@router.get("/auth/me", response_model=UserInfo, summary="获取当前用户信息")
async def get_current_user_info(current_user: UserInfo = Depends(get_current_user)):
    """获取当前登录用户信息"""
    return current_user


@router.post("/auth/verify", summary="验证Token")
async def verify_token(token_data: TokenData = Depends(verify_token)):
    """验证Token有效性"""
    return {
        "success": True,
        "message": "Token有效",
        "user_id": token_data.user_id,
        "username": token_data.username,
        "user_type": token_data.user_type
    }


# 管理员功能：强制用户登出
@router.post("/admin/force_logout/{user_id}", summary="强制用户登出")
async def admin_force_logout(user_id: int, current_user: UserInfo = Depends(get_current_user)):
    """强制用户登出（需要管理员权限）"""
    if current_user.user_type != 2:  # 2是管理员
        return {
            "success": False,
            "message": "权限不足，需要管理员权限"
        }

    success = await auth_service.force_logout(user_id)
    return {
        "success": success,
        "message": f"用户{user_id}已被强制登出" if success else "强制登出失败"
    }


# 调试接口
@router.get("/debug/tokens", summary="查看所有token")
async def debug_tokens():
    """调试接口：查看所有token"""
    tokens = redis_client.get_all_tokens()
    return {
        "token_count": len(tokens),
        "tokens": tokens
    }


@router.delete("/debug/tokens", summary="清空所有token")
async def debug_clear_tokens():
    """调试接口：清空所有token"""
    success = redis_client.flush_all_tokens()
    return {
        "success": success,
        "message": "已清空所有token" if success else "清空token失败"
    }


# 保护的路由示例
@router.get("/protected")
async def protected_route(current_user: UserInfo = Depends(get_current_user)):
    return {
        "message": f"Hello {current_user.username}, this is a protected route!",
        "user_type": current_user.user_type,
        "timestamp": datetime.datetime.now().isoformat()
    }


# 用户管理路由
@router.post("/addUser", response_model=AddUserResponse, summary="添加用户", description="管理员添加新用户")
async def add_user(
    user_data: AddUserRequest,
    current_user: UserInfo = Depends(get_current_user)
):
    """添加新用户（需要管理员权限）"""
    print(f"当前用户信息: {current_user}")
    return await auth_service.add_user(user_data, current_user)